package com.qingyun.schedule.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import com.qingyun.common.dto.Result;
import com.qingyun.schedule.client.StudentClient;
import com.qingyun.schedule.dto.ScheduleDTO;
import com.qingyun.schedule.entity.Course;
import com.qingyun.schedule.entity.Schedule;
import com.qingyun.schedule.entity.Student;
import com.qingyun.schedule.mapper.CourseMapper;
import com.qingyun.schedule.mapper.ScheduleMapper;
import com.qingyun.schedule.service.ICourseService;
import com.qingyun.schedule.service.IScheduleService;
import com.qingyun.schedule.vo.ScheduleStudentVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.cache.CaffeineCacheMetrics;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;


/**
 * <p>
 * 教师课表安排 服务实现类
 * </p>
 *
 * @author your_name
 * @since 2025-08-23
 */
@Slf4j
@Service
public class ScheduleServiceImpl extends ServiceImpl<ScheduleMapper, Schedule> implements IScheduleService {



    @Autowired
    private StudentClient studentClient;
    @Autowired
    private ICourseService courseServiceImpl;

    // 提取为常量，避免重复创建
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final Cache<Long,List<ScheduleDTO>> cache;

    @Autowired
    public ScheduleServiceImpl(MeterRegistry meterRegistry) {
        this.cache = Caffeine.newBuilder()
                .expireAfterWrite(1, TimeUnit.HOURS)
                .maximumSize(100)
                .recordStats()
                .build();
        CaffeineCacheMetrics.monitor(meterRegistry, this.cache, "schedule_cache");
    }
    @Override
    public Result querySchedule(Long teacherId, String dateStr) {
        try {

            // 解析前端传递的日期
            LocalDate date = LocalDate.parse(dateStr, FORMATTER);

            // 计算周一和周日
            LocalDate monday = date.with(DayOfWeek.MONDAY);
            LocalDate sunday = monday.plusDays(6);

            // 判定是否为本周, 若为本周，则从服务器内存中取
            LocalDate currentMonday = LocalDate.now().with(DayOfWeek.MONDAY);
            List<ScheduleDTO> scheduleDTOS = null;
            if (monday.equals(currentMonday)) {
                log.info("当前日期为本周, 从内存中获取本周课表信息");
                scheduleDTOS = loadCache(teacherId);
                if (scheduleDTOS != null && !scheduleDTOS.isEmpty()) {
                    return Result.ok(scheduleDTOS);
                }
                log.info("本地内存暂无该教师本周课表信息");
            }

            // 构建查询条件
            LambdaQueryWrapper<Schedule> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Schedule::getTeacherId, teacherId)
                    .between(Schedule::getTeachDate, monday, sunday)
                    .orderByAsc(Schedule::getTeachDate)
                    .orderByAsc(Schedule::getStartTime);

            // 执行查询
            List<Schedule> schedules = baseMapper.selectList(queryWrapper);


            if(schedules.isEmpty()){
                return Result.fail("暂无本周课表信息");
            }
            // 转换为DTO并填充课程信息
            scheduleDTOS = convertToDTO(schedules);

            log.debug("组装后的课表数据: {}", scheduleDTOS);
            // 仅缓存本周数据
            if (monday.equals(currentMonday)) {
                saveCache(teacherId, scheduleDTOS);
            }
            return Result.ok(scheduleDTOS);
        } catch (DateTimeParseException e) {
            return Result.fail("日期格式错误，请使用yyyy-MM-dd格式");
        } catch (Exception e) {
            log.error("查询课表失败", e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

//    @Override
//    public Result queryScheduleToFeedback(Long teacherId, String dateStr) {
//        LambdaQueryWrapper<Schedule> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Schedule::getTeacherId, teacherId)
//                .eq(Schedule::getTeachDate,dateStr)
//                .orderByAsc(Schedule::getStartTime);
//        return null;
//    }



    @Override
    public Result queryStudentSchedule(Long teacherId, String dateStr, Long studentId) {
        List<ScheduleStudentVO> list = baseMapper.queryStudentScheduleJoined(studentId, teacherId, dateStr);
        if (list == null || list.isEmpty()) {
            return Result.ok(new ArrayList<>());
        }
        return Result.ok(list);
    }

    /**
     * 将Schedule实体转换为DTO并填充课程信息
     */
    private List<ScheduleDTO> convertToDTO(List<Schedule> schedules) {
        List<ScheduleDTO> dtos = new ArrayList<>(schedules.size());

        for (Schedule schedule : schedules) {
            ScheduleDTO dto = new ScheduleDTO();
            // 复制基本属性
            dto.setId(schedule.getId());
            dto.setTeacherId(schedule.getTeacherId());
            dto.setCourseId(schedule.getCourseId());
            dto.setTeachDate(schedule.getTeachDate());
            dto.setStartTime(schedule.getStartTime());
            dto.setEndTime(schedule.getEndTime());
            dto.setPlace(schedule.getPlace());
            dto.setNote(schedule.getNote());
            Student student = studentClient.queryStudentById(schedule.getStudentId());
            dto.setStudentName(student.getName());
            // 查询课程信息名称
            Course course = courseServiceImpl.getById(schedule.getCourseId());
            dto.setCourseName(course.getName());


            dtos.add(dto);
        }
        return dtos;
    }

    public void saveCache(Long teacherId, List<ScheduleDTO> scheduleDTOS){
        cache.put(teacherId, scheduleDTOS);
    }

    public List<ScheduleDTO> loadCache(Long teacherId){
        List<ScheduleDTO> scheduleDTOs = cache.getIfPresent(teacherId);
        // 判定本地缓存是否有数据
        if (scheduleDTOs == null || scheduleDTOs.isEmpty()) {
            return null;
        }
        return scheduleDTOs;
    }
}
